var map;
var proj3857   = new OpenLayers.Projection("EPSG:3857");
var proj900913 = new OpenLayers.Projection("EPSG:900913");
var proj4326   = new OpenLayers.Projection("EPSG:4326");
var wmsUrls = {};

var dNow = new Date();
dNow.setUTCMinutes(0);
dNow.setUTCSeconds(0);
dNow.setUTCMilliseconds(0);
var dMin;
var dMax;

var mapMessages = {
   fading  : true
  ,opacity : 0
  ,hits    : 0
};

function init() {
  var loadingMask = Ext.get('loading-mask');
  var loading = Ext.get('loading');

  //Hide loading message
  loading.fadeOut({duration : 0.2,remove : true});

  //Hide loading mask
  loadingMask.setOpacity(0.9);
  loadingMask.shift({
     xy       : loading.getXY()
    ,width    : loading.getWidth()
    ,height   : loading.getHeight()
    ,remove   : true
    ,duration : 1
    ,opacity  : 0.1
    ,easing   : 'bounceOut'
  });

  Ext.QuickTips.init();

  var oilSpillLayersGridPanelSM = new Ext.grid.CheckboxSelectionModel({
     header    : ''
    ,listeners : {
       rowdeselect : function(sm,idx,rec) {
         if (new RegExp(/^OM_/).test(rec.get('val'))) {
           var p     = rec.get('val').split(':');
           var name  = p.slice(1).join(':');
           var param = {};
           param[p[0]] = false;
           var lyr = map.getLayersByName(name)[0];
           lyr.mergeNewParams(param);
         }
         else {
           map.getLayersByName(rec.get('val'))[0].setVisibility(false);
         }
       }
       ,rowselect : function(sm,idx,rec) {
         if (new RegExp(/^OM_/).test(rec.get('val'))) {
           var p     = rec.get('val').split(':');
           var name  = p.slice(1).join(':');
           var param = {};
           param[p[0]] = true;
           var lyr = map.getLayersByName(name)[0];
           lyr.mergeNewParams(param);
         }
         else {
           map.getLayersByName(rec.get('val'))[0].setVisibility(true);
         }
       }
    }
  });

  new Ext.Viewport({
     layout : 'border'
    ,id     : 'viewport'
    ,items  : [
      {
         region    : 'north'
        ,html      : ' '
        ,height    : Number(banner.height)
        ,border    : false
        ,bodyStyle : banner.body
      }
      ,{
         region      : 'east'
        ,collapsible : true
        ,title       : 'Control Panel'
        ,id          : 'controlPanel'
        ,bodyStyle   : 'padding:3px'
        ,width       : 310
        ,autoScroll  : true
        ,items       : [
          {id : 'queryFiltersPanel',border : false,bodyStyle : 'padding:2px 2px 0',items : [
            new Ext.form.FieldSet({
               title          : '&nbsp;Oil spill&nbsp;'
              // ,checkboxToggle : true
              ,items          : new Ext.TabPanel({
                 activeTab  : 0
                ,width      : 275
                ,height     : 240
                ,plain      : true
                ,resizeTabs : true
                ,tabWidth   : 75
                ,id         : 'oilSpillTabPanel'
                ,items      : [
                  {
                     title     : 'Home'
                    ,id        : 'oilSpillSummaryTab'
                    ,tbar      : [
                      {
                         text    : 'New'
                        ,icon    : 'img/document_empty.png'
                        ,tooltip     : 'Create a new scenario'
                        ,handler : function() {scenarioWizard('Create a new oil spill scenario')}
                      }
                      ,' '
                      ,' '
                      ,{
                         text    : 'Open'
                        ,icon    : 'img/folder.png'
                        ,tooltip     : 'Open an existing scenario'
                        ,handler : function() {
                          var win = new Ext.Window({
                             width  : 640
                            ,height : 480
                            ,title  : 'Open an existing oil spill scenario'
                            ,layout : 'fit'
                            ,modal  : true
                            ,items  : new Ext.grid.GridPanel({
                               height           : 10
                              ,id               : 'openOilSpillScenarioGridPanel'
                              ,border           : false
                              ,enableHdMenu     : false
                              ,loadMask         : true
                              ,store            : new Ext.data.JsonStore({
                                 url    : 'getOilSpillScenarios.php'
                                   + '?clientKey='   + config.clientKey
                                   + '&location='    + config.location
                                   + '&targetNs='    + config.targetNs
                                   + '&loadSaveUrl=' + config.loadSaveUrl
                                   + '&searchType='  + 'location'
                                ,root   : 'data'
                                ,fields : [{name : 'caseName',sortType : Ext.data.SortTypes.asUCString},'startDate','duration','id']
                                ,autoLoad : true
                                ,sortInfo : {field : 'caseName',direction : 'ASC'}
                              })
                              ,autoExpandColumn : 'caseName'
                              ,sm               : new Ext.grid.RowSelectionModel({
                                singleSelect : true
                              })
                              ,columns          : [
                                 {id : 'caseName',dataIndex : 'caseName',header : 'Name',sortable : true}
                                ,{id : 'startDate',dataIndex : 'startDate',header : 'Simulation start time',sortable : true,type : 'date',dateFormat:'Y-m-d H:i',width : 150,align : 'center'}
                                ,{id : 'duration',dataIndex : 'duration',header : 'Simulation duration (h)',sortable : true,width : 125,align : 'center'}
                              ]
                            })
                            ,buttons : [
                               {text : 'Open',handler : function() {
                                 var sm = Ext.getCmp('openOilSpillScenarioGridPanel').getSelectionModel().getSelections();
                                 if (sm.length > 0) {
                                   win.hide();
                                   resetScenarioResults('Loading');
                                   new Ext.data.JsonStore({
                                      url       : 'getOilSpillScenarios.php'
                                        + '?clientKey='   + config.clientKey
                                        + '&location='    + config.location
                                        + '&targetNs='    + config.targetNs
                                        + '&loadSaveUrl=' + config.loadSaveUrl
                                        + '&searchType='  + 'sid'
                                        + '&sid='         + sm[0].get('id')
                                     ,root      : 'data'
                                     ,fields    : ['caseName','startDate','duration','id','path','env','oil','lon','lat']
                                     ,autoLoad  : true
                                     ,listeners : {load : function(spillSto) {
                                       if (spillSto.getCount() > 0) {
                                         var spillRec = spillSto.getAt(0);
                                         new Ext.data.JsonStore({
                                            url    : 'getOilSpillCurrentsWinds.php'
                                              + '?clientKey=' + config.clientKey
                                              + '&bbox='      + '-180,-90,180,90'
                                              + '&windsCurrents=winds,currents'
                                           ,root   : 'data'
                                           ,fields : ['id','description','wmsLayer','type']
                                           ,autoLoad : true
                                           ,listeners : {load : function(currentsWindsSto) {
                                             var winds    = {
                                                description : null
                                               ,wmsLayer    : null
                                             };
                                             var currents = {
                                                description : null
                                               ,wmsLayer    : null
                                             };
                                             var env      = spillRec.get('env');
                                             if (env) {
                                               for (var i = 0; i < env.length; i++) {
                                                 if (env[i].type == 'W') {
                                                   currentsWindsSto.each(function(r) {
                                                     if (r.get('type') == 'winds' && r.get('id') == env[i].envType) {
                                                       winds = {
                                                          description : r.get('description')
                                                         ,wmsLayer    : r.get('wmsLayer')
                                                       };
                                                     }
                                                   });
                                                 }
                                                 else if (env[i].type == 'C') {
                                                   currentsWindsSto.each(function(r) {
                                                     if (r.get('type') == 'currents' && r.get('id') == env[i].envType) {
                                                       currents = {
                                                          description : r.get('description')
                                                         ,wmsLayer    : r.get('wmsLayer')
                                                       };
                                                     }
                                                   });
                                                 }
                                               }
                                             }
                                             clearScenario();
                                             var d = spillRec.get('startDate').split(/ |-|:/);
                                             dMin = new Date(Date.UTC(d[0],d[1] - 1,d[2],d[3],d[4],0,0));
                                             dMax = new Date(dMin.getTime() + spillRec.get('duration') * 3600000)
                                             dNow = dMin;
                                             setMapTime();
                                             showScenarioResults(
                                               {
                                                  clientKey : config.clientKey
                                                 ,simLength : Number(spillRec.get('duration'))
                                                 ,lon       : spillRec.get('lon')
                                                 ,lat       : spillRec.get('lat')
                                                 ,zoom      : config.oilSpillScenarioZoom
                                               }
                                               ,{
                                                  'Scenario start'         : spillRec.get('startDate').split(' ')[0] + ' at ' + spillRec.get('startDate').split(' ')[1] + ' UTC'
                                                 ,'Simulation duration'    : spillRec.get('duration') + ' hour(s)'
                                                 ,'Spill type'             : spillRec.get('oil')[0].oilType
                                                 ,'Spill amount'           : spillRec.get('oil')[0].amount + ' ' + spillRec.get('oil')[0].amountUnits
                                                 ,'Spill release duration' : spillRec.get('oil')[0].releaseDuration + ' hour(s)'
                                                 ,'Winds'                  : winds.description
                                                 ,'Currents'               : currents.description
                                               }
                                               ,{
                                                  'Currents'               : currents.wmsLayer
                                                 ,'Winds'                  : winds.wmsLayer
                                               }
                                               ,false
                                               ,{
                                                 responseText              : spillRec.get('path')
                                               }
                                             );
                                           }}
                                         });
                                       }
                                       else {
                                         Ext.getCmp('oilSpillSummaryTab').getEl().unmask();
                                         Ext.Msg.alert('Scenario open error',"We're sorry, but there was a fatal problem opening this scenario.");
                                       }
                                     }}
                                   });
                                 }
                                 else {
                                   Ext.Msg.alert('Scenario open error','Please select a scenerio to continue.');
                                 }
                               }}
                              ,{text : 'Refresh',handler : function() {win.items.get(0).getStore().load()}}
                              ,{text : 'Cancel',handler : function() {win.hide()}}
                            ]
                          });
                          win.show();
                        }
                      }
                      ,'->'
                      ,{
                         text    : 'Clear'
                        ,icon    : 'img/cancel.png'
                        ,tooltip : 'Clear scenario from map'
                        ,handler : function() {
                          clearScenario();
                        }
                      }
                    ]
                    ,layout : 'fit'
                    ,items  : {bodyStyle:'background-image:url("img/warning64-lite.png");background-repeat:no-repeat;background-position:center;padding:6px',cls : 'directionsText',html : 'No active oil spill scenario! Please create a new scenario or open an existing scenario to continue.',border : false}
                  }
                  ,{
                     title    : 'Layers'
                    ,id       : 'oilSpillLayersTab'
                    ,disabled : true
                    ,items    : new Ext.grid.GridPanel({
                       id          : 'oilSpillLayersGridPanel'
                      ,height      : 210
                      ,border      : false
                      ,hideHeaders : true
                      ,autoScroll  : true
                      ,store       : new Ext.data.ArrayStore({
                        fields : ['lbl','val']
                      })
                      ,sm               : oilSpillLayersGridPanelSM
                      ,columns          : [oilSpillLayersGridPanelSM,{id : 'lbl',dataIndex : 'lbl'}]
                      ,autoExpandColumn : 'lbl'
                      ,tbar             : [
                        {
                           text    : 'Hide all layers'
                          ,icon    : 'img/lightbulb_off.png'
                          ,tooltip : 'Hide all layers'
                          ,handler : function() {
                            Ext.getCmp('oilSpillLayersGridPanel').getSelectionModel().clearSelections();
                          }
                        }
                        ,'->'
                        ,{
                           text    : 'Show all layers'
                          ,tooltip : 'Show all layers'
                          ,icon    : 'img/lightbulb.png'
                          ,handler : function() {
                            Ext.getCmp('oilSpillLayersGridPanel').getSelectionModel().selectAll();
                          }
                        }
                      ]
                    })
                  }
                  ,{
                     title    : 'Legends'
                    ,id       : 'oilSpillLegendsTab'
                    ,disabled : true
                    ,items    : new Ext.grid.GridPanel({
                       id          : 'oilSpillLegendsGridPanel'
                      ,height      : 210
                      ,border      : false
                      ,hideHeaders : true
                      ,autoScroll  : true
                      ,store       : new Ext.data.ArrayStore({
                        fields : ['lbl','img']
                      })
                      ,columns          : [{id : 'img',dataIndex : 'img'}]
                      ,autoExpandColumn : 'img'
                    })
                  }
                ]
              })
              ,listeners : {
                collapse : function() {
                }
                ,expand  : function() {
                }
              }
            })
          ]}
        ]
        ,tbar : {items : [
           '->'
          ,{
             icon    : 'img/door_out.png'
            ,text    : 'Logout'
            ,tooltip : 'Logout of this map session'
            ,handler : function() {
              document.location = 'logout.php';
            }
          }
        ]}
      }
      ,{
         region    : 'center'
        ,layout    : 'border'
        ,items     : [
          {
             split     : true
            ,region    : 'center'
            ,id        : 'mapPanel'
            ,html      : '<div id="map"><div id="mapMessagesButtonGroup"></div><div id="forecastPanelShowButton"></div></div>'
            ,border    : false
            ,bbar      : {items : [
              {
                 xtype     : 'buttongroup'
                ,autoWidth : true
                ,columns   : 1
                ,title     : 'Map date & time'
                ,items     : [{
                   id    : 'mapTime'
                  ,text  : dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0') + ' ' + String.leftPad(dNow.getUTCHours(),2,'0') + ':00 UTC'
                  ,width : 135
                }]
              }
              ,{
                 xtype     : 'buttongroup'
                ,id        : 'scenarioTimeSliderButtonGroup'
                ,autoWidth : true
                ,columns   : 7
                ,title     : 'Oil spill scenario time controls'
                ,hidden    : true
              }
              ,'->'
              ,{
                 xtype     : 'buttongroup'
                ,autoWidth : true
                ,columns   : 2
                ,title     : 'Map options'
                ,items     : [
                  {text : 'Reset zoom',icon : 'img/zoom_extend16.png',handler : function() {map.setCenter(new OpenLayers.LonLat(center[0],center[1]).transform(proj4326,proj900913),zoom)}}
                  ,{text : 'Basemap',icon : 'img/world16.png',menu : {items : [
                    {
                       text         : 'ESRI Ocean'
                      ,checked      : defaultBasemap == 'ESRI Ocean'
                      ,group        : 'basemap'
                      ,handler      : function() {
                        var lyr = map.getLayersByName('ESRI Ocean')[0];
                        if (lyr.isBaseLayer) {
                          lyr.setOpacity(1);
                          map.setBaseLayer(lyr);
                          lyr.redraw();
                        }
                      }
                    }
                    ,'-'
                    ,{
                       text         : 'Google Hybrid'
                      ,checked      : defaultBasemap == 'Google Hybrid'
                      ,group        : 'basemap'
                      ,handler      : function() {
                        var lyr = map.getLayersByName('Google Hybrid')[0];
                        if (lyr.isBaseLayer) {
                          lyr.setOpacity(1);
                          map.setBaseLayer(lyr);
                          lyr.redraw();
                        }
                      }
                    }
                    ,{
                       text         : 'Google Satellite'
                      ,checked      : defaultBasemap == 'Google Satellite'
                      ,group        : 'basemap'
                      ,handler      : function() {
                        var lyr = map.getLayersByName('Google Satellite')[0];
                        if (lyr.isBaseLayer) {
                          lyr.setOpacity(1);
                          map.setBaseLayer(lyr);
                          lyr.redraw();
                        }
                      }
                    }
                    ,{
                       text         : 'Google Terrain'
                      ,checked      : defaultBasemap == 'Google Terrain'
                      ,group        : 'basemap'
                      ,handler      : function() {
                        var lyr = map.getLayersByName('Google Terrain')[0];
                        if (lyr.isBaseLayer) {
                          lyr.setOpacity(1);
                          map.setBaseLayer(lyr);
                          lyr.redraw();
                        }
                      }
                    }
                    ,'-'
                    ,{
                       text         : 'OpenStreetMap'
                      ,checked      : defaultBasemap == 'OpenStreetMap'
                      ,group        : 'basemap'
                      ,handler      : function() {
                        var lyr = map.getLayersByName('OpenStreetMap')[0];
                        if (lyr.isBaseLayer) {
                          lyr.setOpacity(1);
                          map.setBaseLayer(lyr);
                          lyr.redraw();
                        }
                      }
                    }
                  ]}}
                ]
              }
            ]}
            ,listeners : {
              afterrender : function(p) {
                initMap();
              }
              ,bodyresize : function(p,w,h) {
                var el = document.getElementById('map');
                if (el) {
                  el.style.width  = w;
                  el.style.height = h;
                  map.updateSize();
                }
              }
            }
          }
        ]
      }
    ]
  });
}

function initMap() {
  OpenLayers.Projection.addTransform("EPSG:4326","EPSG:3857",OpenLayers.Layer.SphericalMercator.projectForward);
  OpenLayers.Projection.addTransform("EPSG:3857","EPSG:4326",OpenLayers.Layer.SphericalMercator.projectInverse);

  OpenLayers.Util.onImageLoadError = function() {this.src = 'img/blank.png';}

  // patch openlayers 2.11RC to fix problem when switching to a google layer
  // from a non google layer after resizing the map
  // http://osgeo-org.1803224.n2.nabble.com/trunk-google-v3-problem-resizing-and-switching-layers-amp-fix-td6578816.html
  OpenLayers.Layer.Google.v3.onMapResize = function() {
    var cache = OpenLayers.Layer.Google.cache[this.map.id];
    cache.resized = true;
  };
  OpenLayers.Layer.Google.v3.setGMapVisibility_old =
  OpenLayers.Layer.Google.v3.setGMapVisibility;
  OpenLayers.Layer.Google.v3.setGMapVisibility = function(visible) {
    var cache = OpenLayers.Layer.Google.cache[this.map.id];
    if (visible && cache && cache.resized) {
      google.maps.event.trigger(this.mapObject, "resize");
      delete cache.resized;
    }
    OpenLayers.Layer.Google.v3.setGMapVisibility_old.apply(this,arguments);
  };

  map = new OpenLayers.Map('map',{
    layers            : [
      new OpenLayers.Layer.XYZ(
         'ESRI Ocean'
        ,'http://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/${z}/${y}/${x}.jpg'
        ,{
           sphericalMercator : true
          ,isBaseLayer       : true
          ,wrapDateLine      : true
        }
      )
      ,new OpenLayers.Layer.OSM(
         'OpenStreetMapOlay'
        ,'http://tile.openstreetmap.org/${z}/${x}/${y}.png'
        ,{
           isBaseLayer : false
        }
      )
      ,new OpenLayers.Layer.OSM(
         'OpenStreetMap'
        ,'http://tile.openstreetmap.org/${z}/${x}/${y}.png'
      )
      ,new OpenLayers.Layer.Google('Google Satellite',{
         type          : google.maps.MapTypeId.SATELLITE
        ,projection    : proj900913
      })
      ,new OpenLayers.Layer.Google('Google Hybrid',{
         type          : google.maps.MapTypeId.HYBRID
        ,projection    : proj900913
      })
      ,new OpenLayers.Layer.Google('Google Map',{
         type          : google.maps.MapTypeId.MAP
        ,projection    : proj900913
      })
      ,new OpenLayers.Layer.Google('Google Terrain',{
         type          : google.maps.MapTypeId.TERRAIN
        ,projection    : proj900913
      })
      ,new OpenLayers.Layer.Vector(
         'scenarioSpillSite'
        ,{styleMap : new OpenLayers.StyleMap({
          'default' : new OpenLayers.Style(OpenLayers.Util.applyDefaults({
             externalGraphic : 'img/target16.png'
            ,pointRadius     : 10
            ,graphicOpacity  : 1
            ,graphicWidth    : 16
            ,graphicHeight   : 16
          }))
        })}
      )
    ]
    ,projection        : proj900913
    ,displayProjection : proj4326
    ,units             : 'm'
    ,maxExtent         : new OpenLayers.Bounds(-20037508,-20037508,20037508,20037508.34)
  });

  map.setBaseLayer(map.getLayersByName(defaultBasemap)[0]);
  map.setCenter(new OpenLayers.LonLat(center[0],center[1]).transform(proj4326,proj900913),zoom);

  map.events.register('moveend',this,function() {
    map.getLayersByName('OpenStreetMapOlay')[0].setVisibility(map.baseLayer.name == 'ESRI Ocean' && map.getZoom() >= 11);
  });
  map.events.register('addlayer',this,function(e) {
    map.setLayerIndex(map.getLayersByName('scenarioSpillSite')[0],map.layers.length - 1);
  });
  map.events.register('click',this,function(e) {
    mapClick(e.xy);
  });

  map.getLayersByName('scenarioSpillSite')[0].events.register('featureadded',this,function(e) {
    var pt = e.feature.geometry.getCentroid().transform(proj3857,proj4326);
    Ext.getCmp('scenarioLongitudeDDDD').setValue(Math.floor(pt.x * 1000000) / 1000000);
    Ext.getCmp('scenarioLatitudeDDDD').setValue(Math.floor(pt.y * 1000000) / 1000000);
    var degLon = Math.floor(pt.x);
    var minLon = (Math.abs(pt.x) - Math.abs(degLon)) * 60;
    Ext.getCmp('scenarioLongitudeDDMM-DD').setValue(degLon);
    Ext.getCmp('scenarioLongitudeDDMM-MM').setValue(Math.floor(minLon * 10000) / 10000);
    var degLat = Math.floor(pt.y);
    var minLat = (Math.abs(pt.y) - Math.abs(degLat)) * 60;
    Ext.getCmp('scenarioLatitudeDDMM-DD').setValue(degLat);
    Ext.getCmp('scenarioLatitudeDDMM-MM').setValue(Math.floor(minLat * 10000) / 10000);
  });

  map.addControl(new OpenLayers.Control.Graticule({
    labelSymbolizer : {
       fontColor   : "#666"
      ,fontSize    : "10px"
      ,fontFamily  : "tahoma,helvetica,sans-serif"
    }
    ,lineSymbolizer  : {
       strokeWidth     : 0.40
      ,strokeOpacity   : 0.75
      ,strokeColor     : "#999999"
      ,strokeDashstyle : "dash"
    }
  }));

  new Ext.ButtonGroup({
     renderTo  : 'mapMessagesButtonGroup'
    ,columns   : 1
    ,autoWidth : true
    ,title     : 'Map messages'
    ,items     : {width : 250,xtype : 'container',autoEl : {tag : 'center'},items : {border : false,id : 'mapMessagesHtml',html : ''}}
  });

  setMapMessagesOpacity();
}

function scenarioWizard(title) {
  if (Ext.getCmp('scenarioWizard')) {
    Ext.getCmp('scenarioWizard').focus();
    return;
  }
  var win = new Ext.Window({
     width     : 500
    ,height    : 500
    ,minWidth  : 500
    ,minHeight : 500
    ,id        : 'scenarioWizard'
    ,title     : title
    ,layout    : 'fit'
    ,bodyStyle : 'background:white'
    ,buttons : [
      {text : 'Previous',disabled : true,id : 'scenarioWizardTabPanelPrevious',handler : function() {
        var tp  = Ext.getCmp('scenarioWizardTabPanel');
        var tab = tp.getActiveTab();
        var idx = tp.items.findIndex('id',tab.id);
        tp.setActiveTab(idx - (idx > 0 ? 1 : 0));
      }}
      ,{text : 'Next',disabled : true,id : 'scenarioWizardTabPanelNext',handler : function() {
        var tp  = Ext.getCmp('scenarioWizardTabPanel');
        var tab = tp.getActiveTab();
        var idx = tp.items.findIndex('id',tab.id);
        tp.setActiveTab(idx + (idx < tp.items.length - 1 ? 1 : 0));
      }}
      ,{text : 'Cancel',handler : function() {win.hide()}}
    ]
    ,defaults : {border : false}
    ,items   : new Ext.TabPanel({
       activeTab  : 0
      ,plain      : true
      ,resizeTabs : true
      ,tabWidth   : 150
      ,defaults   : {border : false,bodyStyle : 'padding:6px',autoScroll : true}
      ,id         : 'scenarioWizardTabPanel'
      ,items      : [
        new Ext.FormPanel({
           title          : 'Scenario'
          ,id             : 'scenarioMainTab'
          ,items          : [
            new Ext.form.FieldSet({title : '&nbsp;Identification&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Name <font color="#15428B">[required]</font>'
                ,columnWidth : 0.45
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 html        : 'Description'
                ,columnWidth : 0.45
              }
              ,{
                 xtype       : 'textfield'
                ,columnWidth : 0.45
                ,allowBlank  : false
                ,id          : 'scenarioName'
                ,listeners  : {change : function(field) {
                  updateScenarioWizardNavigation();
                }}
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 xtype       : 'textarea'
                ,columnWidth : 0.45
                ,autoScroll  : true
                ,id          : 'scenarioDescription'
              }
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Location&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Enter spill site coordinates manually ...'
                ,cls         : 'directionsText'
                ,columnWidth : 0.65
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 html        : 'OR ...'
                ,cls         : 'directionsText'
                ,columnWidth : 0.25
              }
              ,{
                 columnWidth : 0.65
                ,defaults    : {border : false}
                ,id          : 'scenarioUnits'
                ,items       : [
                  {
                     layout      : 'column'
                    ,id          : 'unitsDD'
                    ,defaults    : {border : false}
                    ,items       : [
                      {
                         html        : 'Latitude (&deg; N) <font color="#15428B">[required]</font>'
                        ,columnWidth : 0.45
                      }
                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }
                      ,{
                         html        : 'Longitude (&deg; E) <font color="#15428B">[required]</font>'
                        ,columnWidth : 0.45
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.45
                        ,id          : 'scenarioLatitudeDDDD'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.45
                        ,id          : 'scenarioLongitudeDDDD'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                    ]
                  } 
                  ,{
                     layout      : 'column'
                    ,id          : 'unitsDDMM'
                    ,defaults    : {border : false}
                    ,hidden      : true
                    ,items       : [
                      {
                         html        : 'Latitude (N) <font color="#15428B">[required]</font>'
                        ,columnWidth : 0.45
                      }
                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }
                      ,{
                         html        : 'Longitude (E) <font color="#15428B">[required]</font>'
                        ,columnWidth : 0.45
                      }

                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.1
                        ,id          : 'scenarioLatitudeDDMM-DD'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                      ,{
                         html        : '&nbsp;&deg;'
                        ,columnWidth : 0.05
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.25
                        ,id          : 'scenarioLatitudeDDMM-MM'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                      ,{
                         html        : '&nbsp;\''
                        ,columnWidth : 0.05
                      }

                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }

                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.1
                        ,id          : 'scenarioLongitudeDDMM-DD'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                      ,{
                         html        : '&nbsp;&deg;'
                        ,columnWidth : 0.05
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.25
                        ,id          : 'scenarioLongitudeDDMM-MM'
                        ,validator   : function(val) {
                          return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                        }
                        ,listeners  : {change : function(field) {
                          updateScenarioWizardNavigation();
                        }}
                      }
                      ,{
                         html        : '&nbsp;\''
                        ,columnWidth : 0.05
                      }

                    ]
                  }
                  ,{
                     layout      : 'column'
                    ,id          : 'unitsDDLTM'
                    ,defaults    : {border : false}
                    ,hidden      : true
                    ,items       : [
                      {
                         html        : 'Northing (m)'
                        ,columnWidth : 0.45
                      }
                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }
                      ,{
                         html        : 'Longitude (m)'
                        ,columnWidth : 0.45
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.45
                      }
                      ,{
                         html        : '&nbsp;'
                        ,columnWidth : 0.1
                      }
                      ,{
                         xtype       : 'textfield'
                        ,columnWidth : 0.45
                      }
                    ]
                  }
                  ,{
                     xtype       : 'radiogroup'
                    ,id          : 'scenarioUnitsRadioGroup'
                    ,columnWidth : 1
                    ,items       : [
                       {boxLabel : 'DD DD'   ,name : 'units',inputValue : 'DD'   ,checked : true}
                      ,{boxLabel : 'DD MM.MM',name : 'units',inputValue : 'DDMM'}
                      ,{boxLabel : 'DDLTM'   ,name : 'units',inputValue : 'DDLTM',disabled : true}
                    ]
                    ,listeners   : {change : function(rg) {
                      Ext.getCmp('scenarioUnits').items.each(function(el) {
                        if (new RegExp(/^units/).test(el.id)) {
                          if (el.id == 'units' + rg.getValue().inputValue) {
                            el.show();
                          }
                          else {
                            el.hide();
                          }
                        }
                      });
                      updateScenarioWizardNavigation();
                    }}
                  }
                ]
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 xtype       : 'button'
                ,scale       : 'large'
                ,icon        : 'img/target32.png'
                ,id          : 'markScenarioSpillSite'
                ,columnWidth : 0.25
                ,enableToggle : true
                ,text        : '<table><tr><td class="buttonText" style="text-align:center">Mark&nbsp;site<br>on&nbsp;map</td></tr></table>'
                ,handler     : function(but) {
                  document.getElementById('mapMessagesButtonGroup').style.visibility = but.pressed ? 'visible' : 'hidden';
                  document.getElementById('mapMessagesHtml').innerHTML = but.pressed ? 'Click on the map to mark the spill site.' : ''; 
                  mapMessages.hits = 0;
                }
              }
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Start date & time&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 xtype       : 'datefield'
                ,columnWidth : 0.30
                ,format      : 'Y-m-d'
                ,value       :  dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0')
                ,id          : 'scenarioStartDate'
                ,allowBlank  : false
                ,listeners  : {change : function(field) {
                  updateScenarioWizardNavigation();
                }}
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.05
              }
              ,{
                 xtype       : 'timefield'
                ,increment   : 60
                ,format      : 'H:i'
                ,columnWidth : 0.20
                ,value       : String.leftPad(dNow.getUTCHours(),2,'0') + ':00'
                ,id          : 'scenarioStartTime'
                ,allowBlank  : false
                ,listeners  : {change : function(field) {
                  updateScenarioWizardNavigation();
                }}
              }
              ,{
                 html        : '&nbsp;&nbsp;UTC'
                ,bodyStyle   : 'padding-top:4px'
                ,columnWidth : 0.10
              }
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Water temperature&nbsp;',layout : 'column',defaults : {border : false},items : [
              new Ext.form.ComboBox({
                 columnWidth : 0.15
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,forceSelection : true
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : makeTemperatureValues()
                })
                ,value          : 20
                ,id             : 'scenarioWaterTemperatureValue'
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.05
              }
              ,new Ext.form.ComboBox({
                 columnWidth    : 0.20
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,forceSelection : true
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : [['deg C'],['deg F']]
                })
                ,value          : 'deg C'
                ,id             : 'scenarioWaterTemperatureUnits'
              })
            ]})
          ]
        })
        ,new Ext.FormPanel({
           title          : 'Spill'
          ,id             : 'scenarioSpillTab'
          ,disabled       : true
          ,items          : [
            new Ext.form.FieldSet({title : '&nbsp;Spill details&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Spill amount'
                ,columnWidth : 0.15
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.05
              }
              ,{
                 html        : 'Spill units'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 html        : 'Spill type'
                ,columnWidth : 0.45
              }
              ,{
                 xtype       : 'textfield'
                ,columnWidth : 0.15
                ,id          : 'scenarioSpillAmount'
                ,value       : 1000
                ,validator   : function(val) {
                  return this.hidden || (!isNaN(parseFloat(val)) && isFinite(val));
                }
                ,listeners  : {change : function(field) {
                  updateScenarioWizardNavigation();
                }}
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.05
              }
              ,new Ext.form.ComboBox({
                 columnWidth    : 0.25
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'lbl'
                ,forceSelection : true
                ,id             : 'scenarioSpillUnits'
                ,value          : 'Tonnes'
                ,store          : new Ext.data.ArrayStore({
                   fields : ['lbl','val']
                  ,data   : makeOilSpillUnitsValues()
                })
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,new Ext.grid.GridPanel({
                 columnWidth      : 0.45
                ,height           : 150
                ,stripeRows       : true
                ,hideHeaders      : true
                ,autoExpandColumn : 'lbl'
                ,id               : 'scenarioSpillType'
                ,bodyStyle        : 'border:1px solid #99BBE8'
                ,sm               : new Ext.grid.RowSelectionModel({
                   singleSelect : true
                  ,listeners    : {rowselect : function() {
                    updateScenarioWizardNavigation()
                  }}
                })
                ,columns         : [{id : 'lbl',dataIndex : 'lbl'}]
                ,store           : new Ext.data.ArrayStore({
                   fields : ['lbl','val']
                  ,data   : makeOilSpillTypeValues()
                })
                ,listeners : {viewready : function(gp) {
                  gp.getSelectionModel().selectRow(gp.getStore().find('lbl','Dubai Crude'));
                }}
              })
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Simulation details&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Simulation duration (hours)'
                ,columnWidth : 0.30
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 html        : 'Model time step (mins)'
                ,columnWidth : 0.60
              }

              ,new Ext.form.ComboBox({
                 columnWidth    : 0.15
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,forceSelection : true
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : makeModelSimulationLengthValues()
                })
                ,value          : 24
                ,id             : 'scenarioSimulationDuration'
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.25
              }
              ,new Ext.form.ComboBox({
                 columnWidth    : 0.15
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,forceSelection : true
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : makeModelTimeSteps()
                })
                ,value          : 20
                ,id             : 'scenarioModelTimeStep'
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.45
              }

              ,{
                 html        : '&nbsp;'
                ,columnWidth : 1
              }

              ,{
                 html        : 'Release duration (hours)'
                ,columnWidth : 0.30
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.1
              }
              ,{
                 html        : 'Output time interval (mins)<br><span class="directionsText">Must be greater than the model time step.</span>'
                ,columnWidth : 0.60
              }

              ,new Ext.form.ComboBox({
                 columnWidth    : 0.15
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,forceSelection : true
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : makeModelReleaseDurationValues()
                })
                ,value          : 0
                ,id             : 'scenarioReleaseDuration'
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.25
              }
              ,new Ext.form.ComboBox({
                 columnWidth    : 0.15
                ,mode           : 'local'
                ,triggerAction  : 'all'
                ,valueField     : 'val'
                ,displayField   : 'val'
                ,forceSelection : true
                ,store          : new Ext.data.ArrayStore({
                   fields : ['val']
                  ,data   : makeModelOutputTimeInterval()
                })
                ,value          : 20
                ,id             : 'scenarioOutputTimeInterval'
              })
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.45
              }
            ]})
          ]
        })
        ,new Ext.FormPanel({
           title          : 'Environment'
          ,id             : 'scenarioEnvironmentTab'
          ,disabled       : true
          ,listeners      : {show : function() {Ext.defer(function() {Ext.getCmp('scenarioWinds').getStore().load();Ext.getCmp('scenarioCurrents').getStore().load()},100)}}
          ,items          : [
            new Ext.form.FieldSet({title : '&nbsp;Winds&nbsp;',layout : 'column',defaults : {border : false},items : [
              new Ext.grid.GridPanel({
                 columnWidth      : 1
                ,height           : 150
                ,stripeRows       : true
                ,hideHeaders      : true
                ,autoExpandColumn : 'description'
                ,bodyStyle        : 'border:1px solid #99BBE8'
                ,sm               : new Ext.grid.RowSelectionModel({
                   singleSelect : true
                  ,listeners    : {rowselect : function() {
                    updateScenarioWizardNavigation()
                  }}
                })
                ,loadMask         : true
                ,id               : 'scenarioWinds'
                ,columns          : [{id : 'description',dataIndex : 'description'}]
                ,store            : new Ext.data.JsonStore({
                   url    : 'getOilSpillCurrentsWinds.php'
                     + '?clientKey=' + config.clientKey
                     + '&bbox='      + map.getExtent().transform(proj3857,proj4326).toBBOX()
                     + '&windsCurrents=winds'
                  ,root   : 'data'
                  ,fields : ['id','description','wmsLayer']
                  ,sortInfo : {field : 'description',direction : 'ASC'}
                  ,listeners : {load : function(sto) {
                    sto.insert(0,new sto.recordType({
                       'id'          : -999
                      ,'description' : 'NONE'
                      ,'wmsLayer'    : ''
                    }));
                  }}
                })
              })
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Currents&nbsp;',layout : 'column',defaults : {border : false},items : [
              new Ext.grid.GridPanel({
                 columnWidth      : 1
                ,height           : 150
                ,stripeRows       : true
                ,hideHeaders      : true
                ,autoExpandColumn : 'description'
                ,bodyStyle        : 'border:1px solid #99BBE8'
                ,sm               : new Ext.grid.RowSelectionModel({
                   singleSelect : true
                  ,listeners    : {rowselect : function() {
                    updateScenarioWizardNavigation()
                  }}
                })
                ,loadMask         : true
                ,id               : 'scenarioCurrents'
                ,columns          : [{id : 'description',dataIndex : 'description'}]
                ,store            : new Ext.data.JsonStore({
                   url    : 'getOilSpillCurrentsWinds.php'
                     + '?clientKey=' + config.clientKey
                     + '&bbox='      + map.getExtent().transform(proj3857,proj4326).toBBOX()
                     + '&windsCurrents=currents'
                  ,root   : 'data'
                  ,fields : ['id','description','wmsLayer']
                  ,sortInfo : {field : 'description',direction : 'ASC'}
                  ,listeners : {load : function(sto) {
                    sto.insert(0,new sto.recordType({
                       'id'          : -999
                      ,'description' : 'NONE'
                      ,'wmsLayer'    : ''
                    }));
                  }}
                })
              })
            ]})
          ]
        })
        ,new Ext.FormPanel({
           title    : 'Review & run'
          ,id       : 'scenarioReviewTab'
          ,disabled : true
          ,items    : [
            new Ext.form.FieldSet({title : '&nbsp;Scenario properties&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Start'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryStart'
              }
              ,{
                 html        : 'Simulation duration'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummarySimulationLength'
              }
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Spill description&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Type'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryType'
              }
              ,{
                 html        : 'Amount'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryAmount'
              }
              ,{
                 html        : 'Release duration'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryReleaseDuration'
              }
            ]})
            ,new Ext.form.FieldSet({title : '&nbsp;Environmental factors&nbsp;',layout : 'column',defaults : {border : false},items : [
              {
                 html        : 'Winds'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryWinds'
              }
              ,{
                 html        : 'Currents'
                ,columnWidth : 0.25
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.75
                ,id          : 'scenarioSummaryCurrents'
              }
            ]})
            ,{border : false,html : '&nbsp;'}
            ,{border : false,html : '&nbsp;'}
            ,{border : false,layout : 'column',defaults : {border : false},items : [
              {
                 html        : '&nbsp;'
                ,columnWidth : 0.38
              }
              ,{
                 xtype       : 'button'
                ,scale       : 'large'
                ,icon        : 'img/server_go32.png'
                ,columnWidth : 0.24
                ,height      : 90
                ,text        : '<table><tr><td class="buttonText" style="text-align:center"><b>Run<br>scenario</b></td></tr></table>'
                ,handler     : function() {runScenario()}
              }
              ,{
                 html        : '&nbsp;'
                ,columnWidth : 0.38
              }
            ]}
          ]
        })
      ]
      ,listeners : {tabchange : function(tp,tab) {
        var idx = tp.items.findIndex('id',tab.id);
        if (idx == 0) {
          Ext.getCmp('scenarioWizardTabPanelPrevious').disable();
        }
        else if (idx == tp.items.length - 1) {
          Ext.getCmp('scenarioWizardTabPanelNext').disable();
        }
        else {
          Ext.getCmp('scenarioWizardTabPanelPrevious').enable();
        }
        if (tab.id == 'scenarioReviewTab') {
          Ext.getCmp('scenarioSummaryStart').update(Ext.getCmp('scenarioStartDate').value + ' at ' + Ext.getCmp('scenarioStartTime').value + ' UTC');
          Ext.getCmp('scenarioSummarySimulationLength').update(Ext.getCmp('scenarioSimulationDuration').getValue() + ' hour(s)');
          Ext.getCmp('scenarioSummaryType').update(Ext.getCmp('scenarioSpillType').getSelectionModel().getSelections()[0].get('lbl'));
          Ext.getCmp('scenarioSummaryAmount').update(Ext.getCmp('scenarioSpillAmount').getValue() + ' ' + Ext.getCmp('scenarioSpillUnits').getValue());
          Ext.getCmp('scenarioSummaryReleaseDuration').update(Ext.getCmp('scenarioReleaseDuration').getValue() + ' hour(s)');
          Ext.getCmp('scenarioSummaryWinds').update(Ext.getCmp('scenarioWinds').getSelectionModel().getSelections()[0].get('description'));
          Ext.getCmp('scenarioSummaryCurrents').update(Ext.getCmp('scenarioCurrents').getSelectionModel().getSelections()[0].get('description'));
        }
        updateScenarioWizardNavigation();
      }}
    })
    ,listeners : {beforehide : function(win) {
      Ext.MessageBox.confirm('Changes may be lost','Are you sure you wish to exit the oil spill scenario wizard?  Any changes you have made will be lost.',function(btn) {
        if (btn == 'yes') {
          win.suspendEvents();
          win.destroy();
          var l = map.getLayersByName('scenarioSpillSite')[0];
          l.removeFeatures(l.features);
          win.resumeEvents();
          document.getElementById('mapMessagesButtonGroup').style.visibility = 'hidden';
        }
      });
      return false;
    }}
  });
  win.show();
}

function makeTemperatureValues() {
  var a = [];
  for (var i = 10; i <= 100; i++) {
    a.push([i]);
  }
  return a;
}

function makeOilSpillUnitsValues() {
  return [
     ['Barrels',5]
    ,['Cubic meters',3]
    ,['Gallons',2]
    ,['Kilograms',7]
    ,['Liters',1]
    ,['Pounds',6]
    ,['Tonnes',4]
  ];
}

function makeOilSpillTypeValues() {
  return [
     ['Bunker C Fuel Oil #6','BUNKER C FUEL OIL %236']
    ,['Diesel Fuel','DIESEL FUEL OIL']
    ,['Diesel','DIESEL']
    ,['Dubai Crude','Dubai Crude']
    ,['Dubai Oil - DP Assay','Dubai Oil - DP Assay']
    ,['Gasoline (leaded)','GASOLINE (LEADED)']
    ,['Gasoline (unleaded)','GASOLINE (UNLEADED)']
    ,['HFO 380','HFO 380']
    ,['Heavy Crude Oil ','HEAVY CRUDE OIL ']
    ,['JP-4(Fuel Oil No. 1)','JP-4(FUEL OIL No. 1)']
    ,['Jet Fuel A-1','JET FUEL A-1']
    ,['Light Crude','LIGHT CRUDE OIL']
    ,['Lower Zakum','Lower Zakum']
    ,['Marine Diesel Fuel','MARINE DIESEL FUEL ']
    ,['Medium Crude','MEDIUM CRUDE OIL']
    ,['Prudhoe Bay Crude','PRUDHOE BAY CRUDE']
  ];
}

function makeModelSimulationLengthValues() {
  var a = [];
  for (var i = 1; i <= 120; i++) {
    a.push([i]);
  }
  return a;
}

function makeModelReleaseDurationValues() {
  var a = [];
  for (var i = 1; i <= 120; i++) {
    a.push([i]);
  }
  return a;
}

function makeModelTimeSteps() {
  return [[5],[10],[20],[30],[60],[90],[120],[180],[300]];
}

function makeModelOutputTimeInterval() {
  return [[5],[10],[20],[30],[60],[90],[120],[180],[300]];
}

function setMapTime() {
  Ext.getCmp('mapTime').setText(dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0') + ' ' + String.leftPad(dNow.getUTCHours(),2,'0') + ':00 UTC');
  var dStr = dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0') + 'T' + String.leftPad(dNow.getUTCHours(),2,'0') + ':00:00';
  for (var i = 0; i < map.layers.length; i++) {
    // WMS layers only
    if (map.layers[i].DEFAULT_PARAMS) {
      map.layers[i].mergeNewParams({TIME : dStr});
    }
  }
}

function mapClick(xy) {
  var l = map.getLayersByName('scenarioSpillSite')[0];
  l.removeFeatures(l.features);
  if (Ext.getCmp('markScenarioSpillSite') && Ext.getCmp('markScenarioSpillSite').pressed) {
    var lonLat = map.getLonLatFromPixel(xy);
    var f      = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonLat.lon,lonLat.lat));
    lonLat.transform(proj900913,proj4326);
    l.addFeatures(f);
    updateScenarioWizardNavigation();
  }
}

function setMapMessagesOpacity() {
  if (mapMessages.hits >= 1) {
    setTimeout('setMapMessagesOpacity()',100);
    return;
  }
  var el = document.getElementById('mapMessagesButtonGroup');
  el.style.opacity = mapMessages.opacity;
  el.style.filter  = 'alpha(opacity=' + (mapMessages.opacity * 100) + ')';
  if (mapMessages.fading) {
    mapMessages.opacity = mapMessages.opacity - 0.1;
  }
  else {
    mapMessages.opacity = mapMessages.opacity + 0.1;
  }
  if (mapMessages.opacity <= 0) {
    mapMessages.fading = false;
  }
  else if (mapMessages.opacity >= 1) {
    mapMessages.fading = true;
    mapMessages.hits++;
  }
  setTimeout('setMapMessagesOpacity()',100);
}

function updateScenarioWizardNavigation() {
  var tp  = Ext.getCmp('scenarioWizardTabPanel');
  var tab = tp.getActiveTab();
  if (tab.id == 'scenarioMainTab') {
    var locationOk = true;
    Ext.getCmp('units' + Ext.getCmp('scenarioUnitsRadioGroup').items.get(0).getGroupValue()).items.each(function(el) {
      if (new RegExp(/^scenario/).test(el.id)) {
        locationOk = locationOk && el.isValid(true);
      }
    });
    if (
      Ext.getCmp('scenarioName').isValid(true)
      && Ext.getCmp('scenarioStartDate').isValid(true)
      && Ext.getCmp('scenarioStartTime').isValid(true)
      && locationOk
    ) {
      Ext.getCmp('scenarioWizardTabPanelNext').enable();
      Ext.getCmp('scenarioSpillTab').enable();
    }
    else {
      Ext.getCmp('scenarioWizardTabPanelNext').disable();
      Ext.getCmp('scenarioSpillTab').disable();
      Ext.getCmp('scenarioEnvironmentTab').disable();
      Ext.getCmp('scenarioReviewTab').disable();
    }
  }
  else if (tab.id == 'scenarioSpillTab') {
    if (Ext.getCmp('scenarioSpillAmount').isValid(true)) {
      Ext.getCmp('scenarioWizardTabPanelNext').enable();
      Ext.getCmp('scenarioEnvironmentTab').enable();
    }
    else {
      Ext.getCmp('scenarioWizardTabPanelNext').disable();
      Ext.getCmp('scenarioEnvironmentTab').disable();
    }
  }
  else if (tab.id == 'scenarioEnvironmentTab') {
    if (Ext.getCmp('scenarioWinds').getSelectionModel().getSelections().length > 0 && Ext.getCmp('scenarioCurrents').getSelectionModel().getSelections().length > 0) {
      Ext.getCmp('scenarioWizardTabPanelNext').enable();
      Ext.getCmp('scenarioReviewTab').enable();
    }
    else {
      Ext.getCmp('scenarioWizardTabPanelNext').disable();
      Ext.getCmp('scenarioReviewTab').disable();
    }
  }
}

function runScenario() {
  var startDate = new Date(Ext.getCmp('scenarioStartDate').getValue().getTime() - new Date().getTimezoneOffset() * 60000);
  dMin = startDate;
  var endDate   = new Date(startDate.getTime() + Ext.getCmp('scenarioSimulationDuration').getValue() * 3600000);
  dMax = endDate;
  var lon       = Ext.getCmp('scenarioLongitudeDDDD').getValue();
  var lat       = Ext.getCmp('scenarioLatitudeDDDD').getValue();
  if (Ext.getCmp('scenarioUnitsRadioGroup').items.get(0).getGroupValue() == 'DDMM') {
    lon = Ext.getCmp('scenarioLongitudeDDMM-DD').getValue() * 1 + 1/60 * Ext.getCmp('scenarioLongitudeDDMM-MM').getValue();
    lat = Ext.getCmp('scenarioLatitudeDDMM-DD').getValue() * 1 + 1/60 * Ext.getCmp('scenarioLatitudeDDMM-MM').getValue();
  }
  var waterTemp = Ext.getCmp('scenarioWaterTemperatureValue').getValue();
  if (Ext.getCmp('scenarioWaterTemperatureUnits').getValue() == 'deg C') {
    waterTemp = waterTemp * 9/5 + 32;
  }
  waterTemp += 'F';
  var params = {
     'AddToDatabase'  : 'false'
    ,'CaseName'       : Ext.getCmp('scenarioName').getValue()
    ,'ChemId'         : 'NONE'
    ,'ClientKey'      : config.clientKey
    ,'Currents'       : Ext.getCmp('scenarioCurrents').getSelectionModel().getSelections()[0].get('id')
    ,'Duration'       : Ext.getCmp('scenarioReleaseDuration').getValue()
    ,'EndDate'        : endDate.getUTCFullYear() + String.leftPad(endDate.getUTCMonth() + 1,2,'0') + String.leftPad(endDate.getUTCDate(),2,'0') + 'T' + String.leftPad(endDate.getUTCHours(),2,'0') + ':00:00'
    ,'FullPath'       : 'true'
    ,'IncLat'         : lat
    ,'IncLon'         : lon
    ,'Location'       : config.location
    ,'ModelStep'      : Ext.getCmp('scenarioModelTimeStep').getValue()
    ,'ModelType'      : 'OILSPILL'
    ,'OilType'        : Ext.getCmp('scenarioSpillType').getSelectionModel().getSelections()[0].get('val')
    ,'OilUnits'       : Ext.getCmp('scenarioSpillUnits').getStore().getAt(Ext.getCmp('scenarioSpillUnits').getStore().find('lbl',Ext.getCmp('scenarioSpillUnits').getValue())).get('val')
    ,'OutputInterval' : Ext.getCmp('scenarioOutputTimeInterval').getValue()
    ,'River'          : 'false'
    ,'StartDate'      : startDate.getUTCFullYear() + String.leftPad(startDate.getUTCMonth() + 1,2,'0') + String.leftPad(startDate.getUTCDate(),2,'0') + 'T' + String.leftPad(startDate.getUTCHours(),2,'0') + ':00:00'
    ,'Volume'         : Ext.getCmp('scenarioSpillAmount').getValue()
    ,'WaterTemp'      : waterTemp
    ,'Winds'          : Ext.getCmp('scenarioWinds').getSelectionModel().getSelections()[0].get('id')
    ,'simLength'      : Ext.getCmp('scenarioSimulationDuration').getValue()
  };
  var a = [];
  for (var i in params) {
    a.push(i + '=' + params[i]);
  }
  // saveScenario specifics
  params.OilUnits = Ext.getCmp('scenarioSpillUnits').getValue();
  params.WaterTemp = params.WaterTemp.slice(0,-1);

  dNow = startDate;
  setMapTime();

  OpenLayers.Request.issue({
     method  : 'POST'
    ,url     : 'proxy.php'
    ,headers : {'Content-Type' : 'application/x-www-form-urlencoded'}
    ,data    : OpenLayers.Util.getParameterString({
      u : 'http://services.asascience.com/ModelService/runmodel.aspx?' + a.join('&')
    })
    ,callback : OpenLayers.Function.bind(
       showScenarioResults
      ,null
      ,{
         clientKey : config.clientKey
        ,simLength : Ext.getCmp('scenarioSimulationDuration').getValue()
        ,lon       : false
        ,lat       : false
        ,zoom      : false
      }
      ,{
         'Scenario start'         : Ext.getCmp('scenarioStartDate').value + ' at ' + Ext.getCmp('scenarioStartTime').value + ' UTC'
        ,'Simulation duration'    : Ext.getCmp('scenarioSimulationDuration').getValue() + ' hour(s)'
        ,'Spill type'             : Ext.getCmp('scenarioSpillType').getSelectionModel().getSelections()[0].get('lbl')
        ,'Spill amount'           : Ext.getCmp('scenarioSpillAmount').getValue() + ' ' + Ext.getCmp('scenarioSpillUnits').getValue()
        ,'Spill release duration' : Ext.getCmp('scenarioReleaseDuration').getValue() + ' hour(s)'
        ,'Winds'                  : Ext.getCmp('scenarioWinds').getSelectionModel().getSelections()[0].get('description')
        ,'Currents'               : Ext.getCmp('scenarioCurrents').getSelectionModel().getSelections()[0].get('description')
      }
      ,{
         'Currents'               : Ext.getCmp('scenarioCurrents').getSelectionModel().getSelections()[0].get('wmsLayer')
        ,'Winds'                  : Ext.getCmp('scenarioWinds').getSelectionModel().getSelections()[0].get('wmsLayer')
      }
      ,params
    )
  });

  var wiz = Ext.getCmp('scenarioWizard');
  wiz.suspendEvents();
  wiz.destroy();
  wiz.resumeEvents();
  resetScenarioResults('Running');
}

function resetScenarioResults(runningLoading) {
  var l = map.getLayersByName('scenarioSpillSite')[0];
  l.removeFeatures(l.features);
  var l = [];
  for (i = 0; i < map.layers.length; i++) {
    if (new RegExp(/^spillScenario:/).test(map.layers[i].name)) {
      l.push(map.layers[i]);
    }
  }
  for (i = 0; i < l.length; i++) {
    map.removeLayer(l[i]);
  }
  Ext.getCmp('oilSpillLayersGridPanel').getStore().removeAll();
  Ext.getCmp('oilSpillLegendsGridPanel').getStore().removeAll();
  document.getElementById('mapMessagesButtonGroup').style.visibility = 'hidden';
  Ext.getCmp('oilSpillTabPanel').setActiveTab(0);
  Ext.getCmp('oilSpillLayersTab').disable();
  Ext.getCmp('oilSpillLegendsTab').disable();
  Ext.getCmp('oilSpillSummaryTab').getEl().mask('<table><tr><td>' + runningLoading + ' scenario...&nbsp;</td><td><img src="js/ext-3.3.0/resources/images/default/grid/loading.gif"></td></tr></table>','mask');
}

function showScenarioResults(params,summary,wmsLayers,createScenario,r) {
  Ext.getCmp('oilSpillSummaryTab').getEl().unmask();
  var lyrSto = Ext.getCmp('oilSpillLayersGridPanel').getStore();
  var legSto = Ext.getCmp('oilSpillLegendsGridPanel').getStore();
  for (var l in wmsLayers) {
    if (wmsLayers[l]) {
      var lyr = new OpenLayers.Layer.WMS(
         'spillScenario:' + l + ':' + r.responseText
        ,'http://coastmap.com/ecop/wms.aspx?'
        ,{
           layers       : wmsLayers[l]
          ,format       : 'image/png'
          ,transparent  : true
          ,styles       : ''
          ,TIME         : dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0') + 'T' + String.leftPad(dNow.getUTCHours(),2,'0') + ':00:00'
        }
        ,{
           projection   : proj3857
          ,isBaseLayer  : false
          ,singleTile   : true
        }
      );
      lyr.events.register('loadstart',this,function(e) {
        layerLoadstartMask(lyr.name);
      });
      lyr.events.register('loadend',this,function(e) {
        layerLoadendUnmask(lyr.name);
      });
      map.addLayer(lyr);
      lyrSto.add(new lyrSto.recordType({
         lbl : lyr.name.split(':')[1]
        ,val : lyr.name
      }));
      legSto.add(new legSto.recordType({
         lbl : lyr.name.split(':')[1]
        ,img : '<img src="img/legend' + lyr.name.split(':')[1] + '.png">'
      }));
    }
  }

  var lyr = new OpenLayers.Layer.WMS(
     'spillScenario:OILMAP:' + r.responseText
    ,'http://services.asascience.com/ecop/wms.aspx?'
    ,{
       layers       : 'OILMAP_ALL'
      ,format       : 'image/png'
      ,transparent  : true
      ,styles       : ''
      ,ClientKey    : params.clientKey
      ,OILMAP_MODEL : r.responseText
      ,OM_CONTOUR   : true
      ,OM_MASS      : true
      ,OM_SPILLETS  : true
      ,OM_SWEPT     : true
      ,OM_TRACKLINE : true
      ,TIME         : dNow.getUTCFullYear() + '-' + String.leftPad(dNow.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dNow.getUTCDate(),2,'0') + 'T' + String.leftPad(dNow.getUTCHours(),2,'0') + ':00:00'
    }
    ,{
       projection   : proj3857
      ,isBaseLayer  : false
      ,singleTile   : true
    }
  );
  lyr.events.register('loadstart',this,function(e) {
    layerLoadstartMask(lyr.name);
  });
  lyr.events.register('loadend',this,function(e) {
    layerLoadendUnmask(lyr.name);
  });
  map.addLayer(lyr);
  lyrSto.add(new lyrSto.recordType({
     lbl : 'Spill : Trackline'
    ,val : 'OM_TRACKLINE:' + lyr.name
  }));
  lyrSto.add(new lyrSto.recordType({
     lbl : 'Spill : Contour of oil thickness'
    ,val : 'OM_CONTOUR:' + lyr.name
  }));
  lyrSto.add(new lyrSto.recordType({
     lbl : 'Spill : Oil thickness'
    ,val : 'OM_MASS:' + lyr.name
  }));
  lyrSto.add(new lyrSto.recordType({
     lbl : 'Spill : Surface oil particles'
    ,val : 'OM_SPILLETS:' + lyr.name
  }));
  lyrSto.add(new lyrSto.recordType({
     lbl : 'Spill : Swept area'
    ,val : 'OM_SWEPT:' + lyr.name
  }));
  legSto.add(new legSto.recordType({
     lbl : 'Spill'
    ,img : '<img src="img/legend' + 'OilSpill' + '.png">'
  }));

  Ext.getCmp('oilSpillSummaryTab').removeAll();
  var tr = ['<td>Scenario name</td><td>' + r.responseText.split('\\').pop().replace(/\.INP$/,'') + '</td>'];
  for (var i in summary) {
    tr.push('<td>' + i + '</td><td>' + (typeof summary[i] == 'string' ? summary[i] : 'NONE') + '</td>');
  }
  Ext.getCmp('oilSpillSummaryTab').add({html : '<table id="oilSpillSummary"><tr>' + tr.join('</tr><tr>') + '</tr></table>',border : false,autoScroll : true});
  Ext.getCmp('oilSpillSummaryTab').doLayout();
  Ext.getCmp('oilSpillLayersTab').enable();
  Ext.getCmp('oilSpillLegendsTab').enable();
  Ext.getCmp('oilSpillTabPanel').setActiveTab(1);
  Ext.defer(function() {
    var sm = Ext.getCmp('oilSpillLayersGridPanel').getSelectionModel();
    sm.suspendEvents();
    sm.selectAll();
    sm.resumeEvents();
  },100);

  if (params.zoom) {
    map.setCenter(new OpenLayers.LonLat(params.lon,params.lat).transform(proj4326,proj900913),params.zoom);
  }

  var bg = Ext.getCmp('scenarioTimeSliderButtonGroup');
  bg.removeAll();
  bg.show();
  bg.add(
    {
       text    : String.leftPad(dMin.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dMin.getUTCDate(),2,'0')
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(0);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
    ,new Ext.Slider({
       width          : 100
      ,id             : 'oilSpillScenarioTimeSlider'
      ,minValue       : 0
      ,maxValue       : params.simLength
      ,increment      : 1
      ,value          : 0
      ,bodyStyle      : 'padding:5px'
      ,plugins        : new Ext.slider.Tip({
        getText : function(thumb) {
          var d = new Date(dMin.getTime() + thumb.value * 3600000);
          return String.format('{0}', d.getUTCFullYear() + '-' + String.leftPad(d.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(d.getUTCDate(),2,'0') + ' ' + String.leftPad(d.getUTCHours(),2,'0') + ':00 UTC');
        }
      })
      ,listeners : {
        changecomplete : function() {
          dNow = new Date(dMin.getTime() + this.getValue() * 3600000);
          setMapTime();
        }
      }
    })
    ,{
       text    : String.leftPad(dMax.getUTCMonth() + 1,2,'0') + '-' + String.leftPad(dMax.getUTCDate(),2,'0')
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(params.simLength);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
    ,{
       text    : '-6h'
      ,icon    : 'img/ButtonRewind.png'
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(Ext.getCmp('oilSpillScenarioTimeSlider').getValue() - 6);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
    ,{
       text    : '-1h'
      ,icon    : 'img/ButtonPlayBack.png'
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(Ext.getCmp('oilSpillScenarioTimeSlider').getValue() - 1);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
    ,{
       text    : '+1h'
      ,icon    : 'img/ButtonPlay.png'
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(Ext.getCmp('oilSpillScenarioTimeSlider').getValue() + 1);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
    ,{
       text    : '+6h'
      ,icon    : 'img/ButtonForward.png'
      ,handler : function() {Ext.getCmp('oilSpillScenarioTimeSlider').setValue(Ext.getCmp('oilSpillScenarioTimeSlider').getValue() + 6);Ext.getCmp('oilSpillScenarioTimeSlider').fireEvent('changecomplete')}
    }
  );
  bg.doLayout();

  if (createScenario) {
    var env = [];
    for (var l in wmsLayers) {
      if (wmsLayers[l] != '') {
        env.push({
           SourceName : 'Forecast Data'
          ,Type       : l.substr(0,1)
          ,ScenarioID : null
          ,Speed      : null
          ,Direction  : null
          ,EnvType    : createScenario[l]
        });
      }
    }

    OpenLayers.Request.issue({
       method  : 'POST'
      ,url     : 'saveOilSpillScenario.php'
      ,headers : {'Content-Type' : 'application/x-www-form-urlencoded'}
      ,data    : OpenLayers.Util.getParameterString({
         loadSaveUrl   : config.loadSaveUrl
        ,targetNs      : config.targetNs
        ,ClientKey     : createScenario.ClientKey
        ,Scenario      : Ext.encode({
           CaseName       : r.responseText.split('\\').pop().replace(/\.INP$/,'')
          ,StartDate      : createScenario.StartDate
          ,Duration       : createScenario.simLength
          ,Lat            : createScenario.IncLat
          ,Lon            : createScenario.IncLon
          ,ModelStep      : createScenario.ModelStep
          ,OutputInterval : createScenario.OutputInterval
          ,WaterTemp      : createScenario.WaterTemp
          ,Path           : r.responseText
          ,Location       : createScenario.Location
        })
        ,OilInfo          : Ext.encode({
           OilType         : createScenario.OilType
          ,Amount          : createScenario.Volume
          ,ReleaseDuration : createScenario.Duration
          ,AmountUnits     : createScenario.OilUnits
        })
        ,Environments  : Ext.encode(env)
      })
    });
  }
}

function clearScenario() {
  var l = [];
  for (i = 0; i < map.layers.length; i++) {
    if (new RegExp(/^spillScenario:/).test(map.layers[i].name)) {
      l.push(map.layers[i]);
    }
  }
  for (i = 0; i < l.length; i++) {
    map.removeLayer(l[i]);
  }
  Ext.getCmp('oilSpillSummaryTab').removeAll();
  Ext.getCmp('oilSpillSummaryTab').add({bodyStyle:'background-image:url("img/warning64-lite.png");background-repeat:no-repeat;background-position:center;padding:6px',cls : 'directionsText',html : 'No active oil spill scenario! Please create a new scenario or open an existing scenario to continue.',border : false});
  Ext.getCmp('oilSpillSummaryTab').doLayout();
  Ext.getCmp('scenarioTimeSliderButtonGroup').removeAll();
  Ext.getCmp('scenarioTimeSliderButtonGroup').hide();
  Ext.getCmp('oilSpillLayersGridPanel').getStore().removeAll();
  Ext.getCmp('oilSpillLegendsGridPanel').getStore().removeAll();
  Ext.getCmp('oilSpillLayersTab').disable();
  Ext.getCmp('oilSpillLegendsTab').disable();
}

function layerLoadstartMask(name) {
  wmsUrls.name = true;
  Ext.getCmp('mapPanel').getEl().mask('<table><tr><td>Updating map...&nbsp;</td><td><img src="js/ext-3.3.0/resources/images/default/grid/loading.gif"></td></tr></table>','mask');
}

function layerLoadendUnmask(name) {
  delete wmsUrls.name;
  var stillLoading = 0;
  for (u in wmsUrls) {
    stillLoading++;
  }
  if (stillLoading == 0) {
    Ext.getCmp('mapPanel').getEl().unmask();
  }
}
